package com.vip.admin.modules.system.controller;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.vip.admin.common.constant.CommonConstant;
import com.vip.admin.common.entity.Result;
import com.vip.admin.common.security.entity.LoginUser;
import com.vip.admin.common.utils.JwtUtil;
import com.vip.admin.common.utils.PasswordShiroUtils;
import com.vip.admin.common.utils.VerifyCodeUtils;
import com.vip.admin.modules.system.entity.SysUser;
import com.vip.admin.modules.system.service.ISysLogService;
import com.vip.admin.modules.system.service.ISysUserService;

import cn.hutool.core.lang.UUID;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;

@Api(tags = "用户登录")
@Log4j2
@RequestMapping("/sys")
@Controller
public class LoginController {
	@Autowired
	EhCacheCacheManager ehcacheManager;

	@Autowired
	ISysUserService sysUserService;
	@Autowired
	ISysLogService sysLogService;

	@ApiOperation("登录接口")
	@PostMapping("/login")
	@ResponseBody
	public Result<JSONObject> login(@RequestBody LoginUser loginUser) {
		Cache cache = ehcacheManager.getCache("userVCode");
		Result<JSONObject> result = new Result<JSONObject>();
		ValueWrapper valueObj = cache.get(loginUser.getCheckKey());
		if (valueObj != null && StringUtils.isNotBlank(valueObj.get().toString())) {
			if (valueObj.get().toString().equalsIgnoreCase(loginUser.getCaptcha())) {
				// if (true) {
				// if (true) {// 开发环境取消验证码
				String username = loginUser.getUsername();
				String password = loginUser.getPassword();
				QueryWrapper<SysUser> queryWrapper = new QueryWrapper<SysUser>();
				queryWrapper.eq("USER_NAME", username);
				SysUser sysUser = sysUserService.getOne(queryWrapper);
				if (sysUser == null) {
					result.error500("该用户不存在，请注册");
					sysLogService.addLog("用户登录失败，用户不存在！", CommonConstant.LOG_TYPE_1, null);
					return result;
				}
				if (CommonConstant.USER_FREEZE == sysUser.getStatus()) {
					sysLogService.addLog("用户登录失败，用户名:" + sysUser.getUserName() + "已冻结！", CommonConstant.LOG_TYPE_1,
							null);
					result.error500("该用户已冻结");
					return result;
				}
				String userpassword = PasswordShiroUtils.getPassword(password, sysUser.getSalt());
				if (!sysUser.getPassword().equals(userpassword)) {
					result.error500("用户名或密码错误");
					return result;
				}
				String token = JwtUtil.sign(username, sysUser.getPassword());
				Cache userCache = ehcacheManager.getCache("userSession");
				userCache.put(token, token);
				JSONObject obj = new JSONObject();
				obj.put("token", token);
				obj.put("userInfo", sysUser);
				result.setData(obj);
				result.success("登录成功");
				sysLogService.addLog("用户名: " + username + ",登录成功！", CommonConstant.LOG_TYPE_1, null);
				return result;
			} else {
				result.error500("验证码错误");
				return result;
			}
		} else {
			result.error500("验证码无效");
			return result;
		}
	}

	@ApiOperation("退出")
	@GetMapping("/logout")
	@ResponseBody
	public Result<?> logout(HttpServletRequest request, HttpServletResponse response) {
		String token = request.getHeader(CommonConstant.HEADER_TOKEN_KEY);
		if (StringUtils.isEmpty(token)) {
			return Result.error("退出登录失败！");
		}
		String username = JwtUtil.getUsername(token);
		QueryWrapper<SysUser> queryWrapper = new QueryWrapper<SysUser>();
		queryWrapper.eq("USER_NAME", username);
		SysUser sysUser = sysUserService.getOne(queryWrapper);
		if (sysUser != null) {
			sysLogService.addLog("用户名: " + sysUser.getRealName() + ",退出成功！", CommonConstant.LOG_TYPE_1, null);
			Cache userCache = ehcacheManager.getCache("userSession");
			userCache.evict(token);
			SecurityUtils.getSubject().logout();
			return Result.ok("退出登录成功！");
		} else {
			return Result.error("Token无效!");
		}
	}

	@GetMapping("/initVerifyCode")
	@ResponseBody
	public Result<?> initVerifyCode() {
		Cache cache = ehcacheManager.getCache("userVCode");
		String vCodeKey = UUID.randomUUID().toString().replaceAll("-", "");
		cache.put(vCodeKey, VerifyCodeUtils.getRandString(4));
		Map<String, Object> map = new HashMap<>();
		map.put("key", vCodeKey);
		return Result.ok(map);
	}

	@RequestMapping("/getVerifyCode/{vkey}")
	public void getVerificationCode(HttpServletResponse response, @PathVariable("vkey") String vKey) {
		OutputStream os = null;
		try {
			int width = 200;
			int height = 69;
			BufferedImage verifyImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			// 生成对应宽高的初始图片
			Cache cache = ehcacheManager.getCache("userVCode");
			ValueWrapper valueObj = cache.get(vKey);
			if (valueObj != null) {
				VerifyCodeUtils.drawRandomText(valueObj.get().toString(), width, height, verifyImg);
			} else {
				VerifyCodeUtils.drawRandomText("重新刷新", width, height, verifyImg);
			}
			// 单独的一个类方法，出于代码复用考虑，进行了封装。
			response.setContentType("image/png");// 必须设置响应内容类型为图片，否则前台不识别
			os = response.getOutputStream(); // 获取文件输出流
			ImageIO.write(verifyImg, "png", os);// 输出图片流
		} catch (IOException e) {
			log.error(e.getMessage());
			e.printStackTrace();
		} finally {
			if (os != null) {
				try {
					os.flush();
					os.close();// 关闭流
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

}
